package com.avic.map.websocket;

import com.alibaba.fastjson.JSONObject;
import com.avic.map.common.constant.LocalResourceConstant;
import com.avic.map.common.model.MapCommonModel;
import com.avic.map.common.model.SocketCommonModel;
import com.avic.map.common.model.enums.SocketDataTypeEnums;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


@Service
@Slf4j
public class MapSocketHandler implements WebSocketHandler {

    //在线用户列表
    private static final Map<String, WebSocketSession> WEB_SOCKET_SESSION_USER_MAP;

    static {
        WEB_SOCKET_SESSION_USER_MAP = new HashMap<>();
    }

    /**
     * 新增socket
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        String id = session.getUri().toString().split("userToken=")[1];
        log.info("成功建立连接userToken{}", id);
        if (StringUtils.isNotEmpty(id)) {
            WEB_SOCKET_SESSION_USER_MAP.put(id, session);
            // 推送当前正在运行的船舶数据
            List<MapCommonModel> shipMapCommonModels = new ArrayList<>();
            LocalResourceConstant.SHIP_CURRENT_POSITION_MAP.forEach((s, mapCommonModel) -> {
                shipMapCommonModels.add(mapCommonModel);
            });
            session.sendMessage(new TextMessage(JSONObject.toJSONString(
                    new SocketCommonModel<>(SocketDataTypeEnums.ARRAY_MAP_COMMON_MODEL, shipMapCommonModels))));

            List<MapCommonModel> carMapCommonModels = new ArrayList<>();
            LocalResourceConstant.CAR_CURRENT_POSITION_MAP.forEach((s, mapCommonModel) -> {
                carMapCommonModels.add(mapCommonModel);
            });
            session.sendMessage(new TextMessage(JSONObject.toJSONString(
                    new SocketCommonModel<>(SocketDataTypeEnums.ARRAY_MAP_COMMON_MODEL, carMapCommonModels))));

            List<MapCommonModel> soldierMapCommonModels = new ArrayList<>();
            LocalResourceConstant.SOLDIER_CURRENT_POSITION_MAP.forEach((s, mapCommonModel) -> {
                soldierMapCommonModels.add(mapCommonModel);
            });
            session.sendMessage(new TextMessage(JSONObject.toJSONString(
                    new SocketCommonModel<>(SocketDataTypeEnums.ARRAY_MAP_COMMON_MODEL, soldierMapCommonModels))));
        }
        log.info("当前在线人数：{}", WEB_SOCKET_SESSION_USER_MAP.size());
    }

    /**
     * 接收socket信息
     */
    @Override
    public void handleMessage(WebSocketSession webSocketSession, WebSocketMessage<?> webSocketMessage) throws Exception {
        log.info("接收到来着客户端的消息 {}", JSONObject.toJSONString(webSocketMessage.getPayload()));
    }

    /**
     * 发送信息给指定用户
     */
    public boolean sendMessageToUser(String clientId, TextMessage message) {
        if (WEB_SOCKET_SESSION_USER_MAP.get(clientId) == null) {
            return false;
        }
        WebSocketSession session = WEB_SOCKET_SESSION_USER_MAP.get(clientId);
        log.info("发送消息 {} 给用户 {}", session, clientId);
        if (!session.isOpen()) {
            return false;
        }
        try {
            session.sendMessage(message);
        } catch (IOException e) {
            log.error("socket发送消息异常{}", e.getMessage());
            return false;
        }
        return true;
    }

    /**
     * 广播信息给所有用户
     */
    public void sendMessageToAllUsers(TextMessage message) {
        Set<String> clientIds = WEB_SOCKET_SESSION_USER_MAP.keySet();
        log.info("广播信息给所有用户 {}, 当前在线用户 {} 人", message, clientIds.size());
        clientIds.forEach(s -> {
            try {
                WebSocketSession session = WEB_SOCKET_SESSION_USER_MAP.get(s);
                if (session.isOpen()) {
                    session.sendMessage(message);
                }
            } catch (IOException e) {
                log.error("socket广播信息异常{}", e.getMessage());
            }

        });
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        if (session.isOpen()) {
            session.close();
        }
        log.error("连接出错");
        WEB_SOCKET_SESSION_USER_MAP.remove(getClientId(session));
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.error("连接已关闭：{}", status);
        WEB_SOCKET_SESSION_USER_MAP.remove(getClientId(session));
        log.info("当前在线人数：{}", WEB_SOCKET_SESSION_USER_MAP.size());
    }

    @Override
    public boolean supportsPartialMessages() {
        return false;
    }

    /**
     * 获取用户标识
     */
    private Integer getClientId(WebSocketSession session) {
        try {
            Integer clientId = (Integer) session.getAttributes().get("WEB_SOCKET_USER_TOKEN");
            return clientId;
        } catch (Exception e) {
            return null;
        }
    }
}
